home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
program
/
tdk_v120.zip
/
DOORKIT2.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-07-23
|
69KB
|
1,972 lines
{
▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀
▀▀ ▀▀ ▀▀ ▀▀ ▀▀
▀▀ ▀▀ ▀▀▀ ▀▀▀▀▀ The DoorKit!
▀▀ ▀▀ ▀▀ ▀▀ ▀▀
▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀
The BBS Door Development Kit By The People - For The People!
Feel free to modify or optimize this code at will. All I ask is that if
find a better way to do things (and you will), please send me a copy of
your modifications. Thanks in advance!....Larry L. Athey....
This is the secondary DoorKit unit with all the artsy/fartsy functions.
This unit also contains all of the really "Functional" routines to make
writing doors easier. Although there are some things in here you might
consider to be redundant, they are mainly in here for cosmetic purposes.}
{$A+,B-,D+,E+,F-,G-,I-,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+}
{$M 65520,0,655360}
UNIT DOORKIT2;
INTERFACE
USES DOS, CRT, DOORKIT1;
CONST
Wraplength : BYTE = 78; {The maximum word length for input driver.}
DVseg : WORD = $B800; {B800=Color, B000=Mono}
DVofs : WORD = $0000; {The OFS is needed in case I/You create routines
that will write to a virtual page, virtual pages
will not always start at 0000. For more exaples
of writing to virtual pages see ANSIUNIT.PAS}
VAR
ProgramName : STRING[80];{Name and version of the current program}
ProgramDesc : STRING[80];{Description of the current program}
ErrLevel : BYTE; {Errorlevel to exit with}
{─--[Headers]-──────────────────────────────────────────────────────────────}
PROCEDURE FillWord(VAR X; Count : WORD; A : BYTE; C : CHAR);
{^ Just like FillChar, except you give it 2 bytes to use for the fill.
This is also a 16 Bit procedure, unlike the 8 Bit fillchar TP uses.
This is useful for filling in a text screen.}
FUNCTION IsOlder(F1,F2 : STRING) : BOOLEAN;
{^ Is file #1 older than file #2?}
FUNCTION GetFileName(InString: String): STRING;
{^ Takes a full path and file name and returns just the file name.}
FUNCTION GetFilePath(InString: String): STRING;
{^ Takes a full path and file name and returns just the path.}
FUNCTION FSize(Fn : PathStr) : LONGINT;
{^ Returns the size of the file "Fn" in bytes.}
FUNCTION FErase(Fn : PathStr) : BOOLEAN;
{^ Erases the file "Fn" from the hard drive.}
FUNCTION FExist(Fn : PathStr) : BOOLEAN;
{^ Returns true if the file "Fn" exists.}
FUNCTION DExist(Fn : PathStr) : BOOLEAN;
{^ Returns true if the directory "Fn" exists.}
PROCEDURE MakeDir(DirName : STRING);
{^ Like MkDir only checks for the directory's existence first.}
FUNCTION CopyFile(SourceFile,TargetFile : STRING) : BYTE;
{^ Copies SourceFile to TargetFile and returns a result code.}
FUNCTION CommaInt(Number : LONGINT) : STRING;
{^ Inserts commas into a number and returns a string of the number with the
commas. ie: s:=Commint(1000000); (* s='1,000,000' *) Makes Larger numbers
easier to read.}
FUNCTION PadLeft(S : STRING; Ch : CHAR; Len : BYTE) : STRING;
{^ Pad the front of the string with CH, up to LEN.}
FUNCTION PadRight(S : STRING; Ch : CHAR; Len : BYTE) : STRING;
{^ Pad the end of the string with CH, up to LEN.}
FUNCTION IStr(N : LONGINT; Pad : BYTE) : STRING;
{^ Converts a number to a string with padding.
Pad = how many 0's will be padded in front of the string, to make
the number a certain length. ie: istr(45,3) = '045'}
FUNCTION IntToStr(N : LONGINT) : STRING;
{^ Converts a number to a string with no 0 padding.}
FUNCTION StrToInt(S : STRING) : LONGINT;
{^ Converts a string to a number. If the string is invalid, 0 is returned.}
FUNCTION BooleanToStr(B : BOOLEAN) : STRING;
{^ Does not produce the same "TRUE" "FALSE" as pascal, but "True" "False".}
FUNCTION BoolToStr(B : BOOLEAN) : STRING;
{^ Converts BOOLEANs to Ys and Ns}
FUNCTION StrToBool(S : STRING) : BOOLEAN;
{^ If S[1] = 'Y' Then StrToBool := TRUE Else StrToBool := FALSE;}
FUNCTION UpChar(Ch : CHAR) : CHAR;
{^ Converts the char to upper case, this also supports some foreign chars.}
FUNCTION LowChar(Ch : CHAR) : CHAR;
{^ Converts the char to lower case. " " ".}
FUNCTION NoPath(Txt : STRING) : STRING;
{^ Removes blankspaces and trailing backslash from a directory name.}
FUNCTION FixPath(Txt : STRING) : STRING;
{^ Adds a trailing backslash to a directory name.}
FUNCTION AllCaps(S : STRING) : STRING;
{^ Conerts a string to upper case (uses Upchar)}
FUNCTION Lower(S : STRING) : STRING;
{^ Converts a string to lower case (uses Lowchar)}
FUNCTION Proper(S : STRING) : STRING;
{^ Converts a string to a properly capitalized string.}
FUNCTION Dup(Ch : CHAR; Times : BYTE) : STRING;
{^ Dups Ch "times" and returns, good for things like: "---------------" }
FUNCTION Center(St : STRING; MaxPlace : BYTE) : STRING;
{^ Center the text string to fit in between MaxPlace.}
FUNCTION StripLead(St : STRING; Ch : CHAR) : STRING;
FUNCTION StripTrail(St : STRING; Ch : CHAR) : STRING;
FUNCTION StripBoth(St : STRING; Ch : CHAR) : STRING;
{^ The above functions will strip characters from the beginning and ends of
a string. "Ch" is the character you wish to strip.}
FUNCTION IntToHex(Num : LONGINT; Digits : BYTE) : STRING;
{^ Converts an integer value to a hexadecimal string.}
FUNCTION HexToInt(HexStr : STRING) : LONGINT;
{^ Converts a hexadecimal string to integer value.}
PROCEDURE HideCursor;
{^ LOCAL ONLY: turns the cursor off}
PROCEDURE ShowCursor;
{^ LOCAL ONLY: turns the cursor on.}
PROCEDURE SetCursorSize(Top,Bot : BYTE);
{^ LOCAL ONLY: Set the size of the cursor. top=top scanline; bot=bottom
scanline of cursor. Both in the range of 1..8. (7,8)="normal" cursor,
(1,8)=block cursor....}
PROCEDURE ShowProgramAd;
{^ This will clear the screen and display a banner teliing the name and
description of your program. You will most likely want to customize
this before you write any doors with this kit.}
PROCEDURE CPrompt(HotKey : CHAR ; Txt : STRING);
{^ Simply draws text on the screen like most BBSes use in the selections in
their file listings and message readers. (ie: [S]election). Keeping the
HotKey and Txt separate is faster than using Copy/Delete on a string.}
PROCEDURE MenuKey(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
{^ Just like CPrompt except this draws the prompt at X/Y coordinates on the
screen. ANSI must be enabled for this to work.}
PROCEDURE YesNoBox;
{^ Simply draws a colored [Y/N] on the screen.}
PROCEDURE FancyPrompt;
{^ Displays a fancy "Your Selection:" on the screen.}
PROCEDURE Select;
{^ Displays a fancy "Select:" on the screen.}
PROCEDURE YnPrompt(Txt : STRING);
{^ Prints your "Txt" on the screen followed by a colored [Y/n].}
PROCEDURE NyPrompt(Txt : STRING);
{^ Prints your "Txt" on the screen followed by a colored [y/N].}
PROCEDURE AnyKey;
{^ Displays a nice "Press Any Key To Continue" prompt and waits for keypress.}
PROCEDURE OutTxt(FG,BG : BYTE ; Txt : STRING);
{^ Special procedure. Prints text on both screens in the colors
specified by the FG and BG variables. If the user does not have
ANSI enabled, then no color codes are sent.}
PROCEDURE OutTxtL(FG,BG : BYTE ; Txt : STRING);
{^ Same as above except a line feed is sent after the text.}
PROCEDURE OutTxtXY(X,Y,FG,BG : BYTE ; Txt : STRING);
{^ Special procedure. Prints text on both screens at X/Y coordinates
in the colors specified by the FG and BG variables. This procedure
requires the user to have ANSI enabled!}
PROCEDURE OutTxtXYL(X,Y,FG,BG : BYTE ; Txt : STRING);
{^ Same as above except a line feed is sent after the text.}
FUNCTION SecretInput(Len : BYTE; Default : STRING) : STRING;
{^ Special procedure. Creates an input field for getting passwords.
the result of all input is hidden from the user's view.}
FUNCTION NameInput(Len : BYTE; Default : STRING) : STRING;
{^ Special procedure. Creates an input field that will automatically
force all input to proper case.}
FUNCTION NormalInput(Len : BYTE; Default : STRING) : STRING;
{^ Special procedure. Creates an input field, all characters accepted}
FUNCTION CapsInput(Len : BYTE; Default : STRING) : STRING;
{^ Special procedure. Creates an input field that will automatically
force all input to upper case letters}
FUNCTION NumberInput(Len : BYTE; Default : STRING) : STRING;
{^ Special procedure. Creates an input field but will only allow the
input of numeric characters}
FUNCTION NamePrompt(StrLength : BYTE ; InStr : STRING) : STRING;
{^ Similar to NameInput except the user is required to have ANSI
enabled. This will produce an input field on the screen filled
with underscores and will have a bracket on both ends.}
FUNCTION NormalPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
{^ Similar to NormalInput but follows the same rules as NamePrompt.}
FUNCTION NumberPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
{^ Similar to NumberInput but follows the same rules as NamePrompt.}
FUNCTION SecretPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
{^ Similar to SecretInput but follows the same rules as NamePrompt.}
FUNCTION CapsPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
{^ Similar to CapsInput but follows the same rules as NameIprompt.}
FUNCTION SysField(X,Y,Style,StrLength : BYTE ; InStr : STRING) : STRING;
{^ Special procedure. Say for example you wanted to create a feature in
your door where you have various input fields at specific locations.
You would use this to draw a fields on the screen. Then you would use
it in conjunction with the next procedure to make it look like your
fields are shifting and showing the field that is active. ANSI must
be enabled. (Style = 0-Normal 1-Number 2-Name 3-Secret 4-Caps)}
PROCEDURE DummyField(X,Y,StrLength : BYTE ; InStr : STRING);
{^ See the above description.}
PROCEDURE DrawWin(X1,Y1,X2,Y2 : BYTE ; Title : STRING);
{^ Draws a window on both screens at X1,Y1,X2,Y2 coordinates with a title.
ANSI graphics required for this.'}
PROCEDURE ClearWin(X1,Y1,X2,Y2 : BYTE);
{^ Clears a window with the CS.Wbg color, ANSI graphics required for this.}
PROCEDURE DrawButton(HotKey : CHAR ; Txt : STRING ; HighLight : BOOLEAN);
{^ Draws a simulated raised button on the screen.}
PROCEDURE SysButton(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
{^ Draws a simulated raised button on the screen at X/Y coorinates. This is
mainly meant to be used with DrawWin since the button uses the window
background color on its edges. ANSI is required for this.}
PROCEDURE DrawMenu(X1,Y1,X2,Y2 : BYTE);
{^ Creates a simulated drop down menu at X1,Y1,X2,Y2, ANSI required.}
PROCEDURE MenuItem(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
{^ Adds a selection to a drop down menu, ANSI required.}
PROCEDURE MenuLine(X,Y,L : BYTE);
{^ Adds a dividing line to a drop down menu, ANSI required.}
PROCEDURE MenuBarItem(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
{^ Since you are making simulated drop down menus, they have to drop down
from a menu bar. Most times a menu bar is nothing more than going to the
1,1 coordinate and doing an sClrEol. After that, you will add items to
your menu bar. ANSI required.}
PROCEDURE InfoBox(Width : BYTE ; Height : BYTE);
{^ Creates a nice 3D frame on the screen, ANSI required.}
PROCEDURE InfoText(Txt : STRING);
{^ Creates a nice banner on the screen just like AnyKey does.}
PROCEDURE LineBar(FG,BG,L : BYTE);
{^ Draws a thin line across the screen in FG/BG colors at L length.}
PROCEDURE RunEntryForm(ScriptFile : STRING);
{^ Runs a Dynamic Entry Form (ie: Script).}
PROCEDURE Log(LogLine : STRING);
{^ Use this if you are using activity logging.}
PROCEDURE Terminate(S : STRING);
{^ Halts the program with the Error String "S".}
PROCEDURE ErrorLog(LogLine : STRING ; ELevel : BYTE ; BailOut : BOOLEAN);
{^ Use this if you are tracking errors in your program. If BailOut is True,
then the program will terminate immediately after writing to the log.}
PROCEDURE CvtColors(InStr : STRING ; LF : BOOLEAN);
{^ Displays a text string with embedded "Fancy Bracket" color codes and
automatically changes color of the text is displayed. (If LF is true,
a linefeed will be sent).}
FUNCTION CvtVars(Txt : STRING) : STRING;
{^ Converts a string with embedded global system veriables to a translated
string. You may add/change variables as you see fit.}
FUNCTION DateVariable : STRING;
{^ Returns a nice MM/DD/YY formatted date string.}
FUNCTION TimeVariable : STRING;
{^ Returns a nice ##:##am or ##:##pm formatted time string.}
PROCEDURE RipToText;
{^ If a caller is connected in RIP graphics mode, you must make a call to
this procedure to throw RIPterm back into text mode. To throw RIPterm
back into RIP graphics mode, simply use ShowScreen() to display a *.RIP}
PROCEDURE ShowTextFile(TextFile : STRING);
{^ This displays a text file to the user in the "Text Reader" where they
can use [P]revious, [N]ext, [T]op, [B]ottom and [Q]uit keys.}
PROCEDURE ShowScreen(Scr : STRING);
{^ This is a non-stop display of an ANSI/ASCII/RIP/MAX screen file where
each line is checked for global system variables and translated.}
PROCEDURE ChatSelect;
{^ This procedure can be called from any other procedure to throw the door
into SysOp/User chat. Depending on the user's graphics capabilities, the
door will decide which chat mode to use. There are split screen chat and
line chat chat modes. Line chat mode will only be used in the event the
caller only has TTY graphics capabilities.}
PROCEDURE AlertTones;
{^ Produces five ^G tones with a 200ms delay between tones. Use this to alert
the user of an error. The sysop will only hear the tones if the door is
running locally, otherwise the tones are sent straight to the comport.}
PROCEDURE DVWrite(X,Y : WORD; Attr : BYTE; S : STRING);
{^ No this doesn't have anything to do with DesqView. This means Direct Video
Write. This allows you to display something on the local screen without it
ever affecting the user's video. You can change colors, move the cursor to
specific X/Y coordinates, you name it, and there is never any effect on the
user's screen. That's just an advantage of writing directly to the video
RAM rather than going through the BIOS.}
{───────────────────────────────────────────────────────────────────────────}
IMPLEMENTATION
USES ANSIUNIT;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE FillWord(VAR X; Count : WORD; A : BYTE; C : CHAR); Assembler;
Asm
les di,X
mov cx,[Count]
shr cx,1
mov al,[C]
mov ah,[A]
rep stosw
test [Count],1 {Just in case you give it an odd count.}
jz @END
stosb
@END :
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION IsOlder(F1,F2 : STRING) : BOOLEAN;
VAR
DInfo1 : SEARCHREC;
DInfo2 : SEARCHREC;
D1 : DATETIME;
D2 : DATETIME;
I1 : LONGINT;
I2 : LONGINT;
BEGIN
IsOlder := FALSE;
FINDFIRST(F1,Archive,DInfo1); I1 := DInfo1.Time; UNPACKTIME(I1,D1);
FINDFIRST(F2,Archive,DInfo2); I2 := DInfo2.Time; UNPACKTIME(I2,D2);
IF (D1.Year < D2.Year) THEN IsOlder := TRUE;
IF (D1.Year = D2.Year) AND (D1.Month < D2.Month) THEN IsOlder := TRUE;
IF (D1.Year = D2.Year) AND (D1.Month = D2.Month) AND (D1.Day < D2.Day) THEN IsOlder := TRUE;
IF (D1.Month = D2.Month) AND (D1.Day = D2.Day) AND (D1.Year = D2.Year) THEN BEGIN
IF (D1.Hour < D2.Hour) THEN IsOlder := TRUE;
IF (D1.Hour = D2.Hour) AND (D1.Min < D2.Min) THEN IsOlder := TRUE;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION GetFileName(InString: String): STRING;
VAR
Work : BYTE;
BEGIN
InString := StripBoth(InString,' ');
REPEAT
Work := POS('\',InString);
IF Work<>0 THEN DELETE(InString,1,Work);
UNTIL Work=0;
GetFileName := InString;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION GetFilePath(InString: String): STRING;
VAR
Loop : BYTE;
BEGIN
InString := StripBoth(InString,' ');
IF InString[Length(InString)]='\' THEN
BEGIN
GetFilePath := InString;
Exit;
END;
Loop := LENGTH(InString);
REPEAT
DEC(Loop);
UNTIL ((Loop=0) OR (InString[Loop]='\'));
IF Loop<>0 THEN DELETE(InString,Loop+1,LENGTH(InString)-Loop) ELSE InString := '';
GetFilePath := InString;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION FSize(Fn : PathStr) : LONGINT;
VAR
F : FILE;
BEGIN
ASSIGN(F,Fn);
RESET(F,1);
IF IORESULT = 0 THEN BEGIN
FSize := FILESIZE(F);
CLOSE(F);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION FErase(Fn : PathStr) : BOOLEAN;
VAR
F : FILE;
BEGIN
ASSIGN(F,Fn);
ERASE(F);
FErase := IORESULT = 0;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION FExist(Fn : PathStr) : BOOLEAN;
VAR
DirInfo : SEARCHREC;
BEGIN
FINDFIRST(Fn,Anyfile - Directory - VolumeID,DirInfo);
FExist := DOSERROR = 0;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION DExist(Fn : PathStr) : BOOLEAN;
VAR
OrgDir : PathStr;
BEGIN
Fn := NoPath(FExpand(Fn));
GETDIR(BYTE(Fn[1]) - BYTE('A') + 1,OrgDir);
CHDIR(Fn);
DExist := IORESULT = 0;
CHDIR(OrgDir);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE MakeDir(DirName : STRING);
BEGIN
DirName := NoPath(AllCaps(DirName));
IF NOT DExist(DirName) THEN MKDIR(DirName);
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION CopyFile(SourceFile,TargetFile : STRING) : BYTE;
{ Return Codes: 0 Successful
1 Source and target the same
2 Cannot open source
3 Unable to create target
4 Error during copy }
VAR
Source,
Target : FILE;
BRead,
BWrite : WORD;
FileBuf : ARRAY[1..2048] OF CHAR;
BEGIN
SourceFile := StripBoth(SourceFile,' ');
TargetFile := StripBoth(TargetFile,' ');
IF SourceFile = TargetFile THEN BEGIN
CopyFile := 1;
EXIT;
END;
ASSIGN(Source,SourceFile);
{$I-}RESET(Source,1);{$I+}
IF IORESULT <> 0 THEN BEGIN
CopyFile := 2;
EXIT;
END;
ASSIGN(Target,TargetFile);
{$I-}REWRITE(Target,1);{$I+}
IF IORESULT <> 0 THEN BEGIN
CopyFile := 3;
EXIT;
END;
REPEAT
BLOCKREAD(Source,FileBuf,SIZEOF(FileBuf),BRead);
BLOCKWRITE(Target,FileBuf,Bread,BWrite);
UNTIL (BRead = 0) OR (BRead <> BWrite);
CLOSE(Source);
CLOSE(Target);
IF BRead <> BWrite THEN CopyFile := 4 ELSE CopyFile := 0;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION CommaInt(Number : LONGINT) : STRING;
VAR
NumStr : STRING[15];
Len : BYTE;
I : BYTE;
BEGIN
STR(Number,NumStr);
Len := LENGTH(NumStr);
I := Len + 1;
WHILE (I > 4) AND (I <= Len + 1) DO BEGIN
DEC(I,3);
INSERT(',',NumStr,I);
END;
CommaInt := NumStr;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION PadRight(S : STRING; Ch : CHAR; Len : BYTE) : STRING;
BEGIN
WHILE LENGTH(S) < Len DO S := S + Ch;
PadRight := S;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION PadLeft(S : STRING; Ch : CHAR; Len : BYTE) : STRING;
BEGIN
WHILE LENGTH(S) < Len DO S := Ch + S;
PadLeft := S;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION IStr(N : LONGINT; Pad : BYTE) : STRING;
VAR
St : STRING[20];
BEGIN
STR(N,St);
WHILE LENGTH(St) < Pad DO INSERT('0',St,1);
IStr := St;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION IntToStr(N : LONGINT) : STRING;
VAR
St : STRING;
BEGIN
STR(N,St);
IntToStr := St;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION StrToInt(S : STRING) : LONGINT;
VAR
L : LONGINT;
U : INTEGER;
BEGIN
VAL(S,L,U);
StrToInt := L;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION BooleanToStr(B : BOOLEAN) : STRING;
BEGIN
IF B THEN BooleanToStr := 'True' ELSE BooleanToStr := 'False';
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION BoolToStr(B : BOOLEAN) : STRING;
BEGIN
IF B THEN BoolToStr := 'Y' ELSE BoolToStr := 'N';
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION StrToBool(S : STRING) : BOOLEAN;
BEGIN
S := StripBoth(S,' ');
S := AllCaps(S);
IF POS('Y',S) = 1 THEN StrToBool := TRUE ELSE StrToBool := FALSE;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION UpChar(Ch : CHAR) : CHAR;
BEGIN
IF Ch IN [#97..#122] THEN Ch := CHR(BYTE(Ch) AND $DF)
ELSE IF Ch = '¢' THEN Ch := '¥' ELSE IF Ch = 'å' THEN Ch := 'Å'
ELSE IF Ch = 'ä' THEN Ch := 'Ä' ELSE IF Ch = 'ç' THEN Ch := 'Ç'
ELSE IF Ch = 'é' THEN Ch := 'É' ELSE IF Ch = 'ö' THEN Ch := 'Ö'
ELSE IF Ch = 'ñ' THEN Ch := 'Ñ' ELSE IF Ch = 'ü' THEN Ch := 'Ü';
UpChar := Ch;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION LowChar(Ch : CHAR) : CHAR;
BEGIN
IF Ch IN [#65..#90] THEN Ch := CHR(BYTE(ch) AND $20)
ELSE IF Ch = '¥' THEN Ch := '¢' ELSE IF Ch = 'Å' THEN Ch := 'å'
ELSE IF Ch = 'Ä' THEN Ch := 'ä' ELSE IF Ch = 'Ç' THEN Ch := 'ç'
ELSE IF Ch = 'É' THEN Ch := 'é' ELSE IF Ch = 'Ö' THEN Ch := 'ö'
ELSE IF Ch = 'Ñ' THEN Ch := 'ñ' ELSE IF Ch = 'Ü' THEN Ch := 'ü';
LowChar := Ch;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION NoPath(Txt : STRING) : STRING;
VAR
Work : BYTE;
BEGIN
Txt := StripBoth(Txt,' ');
Txt := StripTrail(Txt,'\');
NoPath := Txt;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION FixPath(Txt : STRING) : STRING;
VAR
Loop,EndCh : BYTE;
BEGIN
Txt := StripBoth(Txt,' ');
EndCh := LENGTH(Txt);
FOR Loop := 1 TO LENGTH(Txt) DO Txt[Loop] := UPCASE(Txt[Loop]);
IF Txt[EndCh] <> '\' THEN Txt := Txt + '\';
FixPath := Txt;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION AllCaps(S : STRING) : STRING;
VAR
SLen : BYTE ABSOLUTE S;
X : INTEGER;
BEGIN
FOR X := 1 TO SLen DO S[X] := UpChar(S[X]);
AllCaps := S;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION Lower(S : STRING) : STRING;
VAR
SLen : BYTE ABSOLUTE S;
I : INTEGER;
BEGIN
FOR I := 1 TO SLen DO S[I] := LowChar(S[I]);
Lower := S;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION Proper(S : STRING) : STRING;
VAR
SLen : BYTE ABSOLUTE S;
I : INTEGER;
BEGIN
S := Lower(S);
FOR I := 1 TO SLen DO BEGIN
IF I = 1 THEN S[1] := UpChar(S[1])
ELSE IF S[I-1] = ' ' THEN S[i] := UpChar(S[i])
ELSE IF (ORD(S[I-1]) IN [32..64]) AND (S[i-1] <> '''')
THEN S[I] := UpChar(S[I]);
END;
Proper := S;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION Dup(ch : CHAR; times : BYTE) : STRING;
VAR
Temp : STRING;
BEGIN
FILLCHAR(Temp[1],Times,Ch);
Temp[0] := CHAR(Times);
Dup := Temp;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION Center(St : STRING; MaxPlace : BYTE) : STRING;
CONST
JustChar : CHAR = ' ';
VAR
Temp : STRING;
Num : BYTE;
BEGIN
Num := (MaxPlace DIV 2) - (LENGTH(St) DIV 2);
Temp := Dup(JustChar,Num);
Temp := Temp + St;
Temp := Temp + Dup(JustChar,MaxPlace - Num - LENGTH(St));
Center := Temp;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION StripLead(St : STRING; Ch : CHAR) : STRING;
VAR
TempStr : STRING;
BEGIN
TempStr := St;
WHILE ((TempStr[1] = Ch) AND (LENGTH(TempStr) > 0)) DO tempstr := COPY(TempStr,2,LENGTH(TempStr));
striplead := tempstr;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION StripTrail(St : STRING; Ch : CHAR) : STRING;
VAR
TempStr : STRING;
I : INTEGER;
BEGIN
TempStr := St;
I := LENGTH(St);
WHILE ((I > 0) AND (St[I] = Ch)) DO I := I - 1;
TempStr[0] := CHR(I);
StripTrail := TempStr;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION StripBoth(St : STRING; Ch : CHAR) : STRING;
BEGIN
StripBoth := StripTrail(StripLead(St,Ch),Ch);
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION IntToHex(Num : LONGINT; Digits : BYTE) : STRING;
CONST
HexId : ARRAY[0..$F] OF CHAR = '0123456789ABCDEF';
VAR
S : STRING;
C : BYTE;
N : ARRAY[1..SIZEOF(LONGINT)] OF BYTE ABSOLUTE Num;
BEGIN
S := '';
FOR C := 4 DOWNTO 1 DO S := S + HexId[N[C] SHR 4] + HexId[N[C] AND $F];
IntToHex := COPY(S,8 - Digits + 1,Digits);
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION HexToInt(HexStr : STRING) : LONGINT;
VAR
I,HexNibble : WORD;
Temp : LONGINT;
Code : INTEGER;
BEGIN
Temp := 0;
HexStr := AllCaps(HexStr);
FOR I := LENGTH(HexStr) DOWNTO 1 DO IF NOT (HexStr[I] IN ['0'..'9','A'..'F']) THEN DELETE(HexStr,I,1);
FOR I := LENGTH(HexStr) DOWNTO 1 DO BEGIN
IF HexStr[I] IN ['0'..'9'] THEN HexNibble := BYTE(HexStr[I]) - BYTE('0')
ELSE HexNibble := BYTE(HexStr[I]) - BYTE('A') + 10;
INC(Temp,LONGINT(HexNibble) * (1 SHL (4 * (LONGINT(LENGTH(HexStr)) - I))));
END;
HexToInt := Temp;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE HideCursor; Assembler;
Asm
Mov ax,0100h
Mov cx,2607h
INT 10h
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ShowCursor; Assembler;
asm
Mov ax,0100h
Mov cx,0506h
INT 10h
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE SetCursorSize(Top,Bot : BYTE); Assembler;
Asm
Mov ah,01h
Mov ch,[Top]
Mov cl,[Bot]
INT 10h
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ShowProgramAd;
BEGIN
sClrScr;
LineBar(1,0,79);
OutTxtL(14,0,ProgramName);
OutTxtL(9,0,ProgramDesc);
OutTxtL(11,0,'Copyright 1995-1996 Larry Athey - BBS Utiliteez Software');
LineBar(1,0,79);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE CPrompt(HotKey : CHAR ; Txt : STRING);
BEGIN
Set_Color(CS.CPBfg,CS.CPBbg); sWriteC('[');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC(HotKey);
Set_Color(CS.CPBfg,CS.CPBbg); sWriteC(']');
Set_Color(CS.CPTfg,CS.CPTbg); sWrite(Txt+' ');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE MenuKey(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
BEGIN
sGotoXY(X,Y);
Set_Color(CS.CPBfg,CS.CPBbg); sWriteC('[');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC(HotKey);
Set_Color(CS.CPBfg,CS.CPBbg); sWriteC(']');
Set_Color(CS.CPTfg,CS.CPTbg); sWrite(Txt);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE YesNoBox;
BEGIN
Set_Color(CS.CPBfg,CS.CPBbg); sWrite(' [');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC('Y');
Set_Color(CS.CPBfg,CS.CPBbg); sWriteC('/');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC('N');
Set_Color(CS.CPBfg,CS.CPBbg); sWrite('] ');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE FancyPrompt;
BEGIN
OutTxt(9,0,'Y');
OutTxt(11,0,'o');
OutTxt(15,0,'ur Selecti');
OutTxt(11,0,'o');
OutTxt(9,0,'n');
OutTxt(8,0,': ');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE Select;
BEGIN
OutTxt(9,0,'S');
OutTxt(11,0,'e');
OutTxt(15,0,'le');
OutTxt(11,0,'c');
OutTxt(9,0,'t');
OutTxt(8,0,':');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE YnPrompt(Txt : STRING);
BEGIN
Set_Color(CS.CPTfg,CS.CPTbg); sWrite(Txt);
Set_Color(CS.CPBfg,CS.CPBbg); sWrite(' [');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC('Y');
Set_Color(CS.CPBfg,CS.CPBbg); sWriteC('/');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC('n');
Set_Color(CS.CPBfg,CS.CPBbg); sWrite('] ');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE NyPrompt(Txt : STRING);
BEGIN
Set_Color(CS.CPTfg,CS.CPTbg); sWrite(Txt);
Set_Color(CS.CPBfg,CS.CPBbg); sWrite(' [');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC('N');
Set_Color(CS.CPBfg,CS.CPBbg); sWriteC('/');
Set_Color(CS.CPKfg,CS.CPKbg); sWriteC('y');
Set_Color(CS.CPBfg,CS.CPBbg); sWrite('] ');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE AnyKey;
BEGIN
Set_Color(1,0); sClrEol; sWrite('░▒▓');
Set_Color(15,1); sWrite(' Press Any Key To Continue ');
Set_Color(1,0); sWrite('▓▒░');
sReadKey;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE OutTxt(FG,BG : BYTE ; Txt : STRING);
BEGIN
Set_Color(FG,BG);
sWrite(Txt);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE OutTxtL(FG,BG : BYTE ; Txt : STRING);
BEGIN
Set_Color(FG,BG);
sWriteln(Txt);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE OutTxtXY(X,Y,FG,BG : BYTE ; Txt : STRING);
BEGIN
sGotoXY(X,Y);
Set_Color(FG,BG);
sWrite(Txt);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE OutTxtXYL(X,Y,FG,BG : BYTE ; Txt : STRING);
BEGIN
sGotoXY(X,Y);
Set_Color(FG,BG);
sWriteln(Txt);
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION InputDriver(Len : BYTE; Name,Showit,AllCap,NumInput : BOOLEAN; tLine : STRING) : STRING;
VAR
Ch : CHAR;
Insrt : BOOLEAN;
Loop,
J,Place : BYTE;
Temp,
RTemp : STRING;
BEGIN
Insrt := TRUE;
IF tLine = '' THEN Place := 1 ELSE Place := LENGTH(tLine)+1;
REPEAT
Ch := sReadKey;
IF Name THEN BEGIN
IF Place = 1 THEN Ch := UPCASE(Ch) ELSE IF tLine[Place-1] = #32 THEN Ch := UPCASE(Ch);
END;
IF AllCap THEN Ch := UPCASE(Ch);
IF (NumInput AND (Ch IN [#0..#31,'0'..'9','-','+'])) OR NOT NumInput THEN
CASE Ch OF
#0,
#22,
#27,
#127:BEGIN
Temp := Ch;
IF Ch = #0 THEN Temp := s_ReadKey;
IF Ch = #27 THEN Temp := Temp + sReadKey + sReadKey;
IF Ch = #22 THEN BEGIN
sWaitInput(250);
IF sKeyPressed THEN Temp := Temp + sReadKey;
END;
J := 0;
REPEAT
IF Temp = CursorMove.Home[J] THEN BEGIN
IF Place-1 <> 0 THEN sCursorLeft(Place-1);
Place := 1;
Temp := '';
END ELSE IF Temp = CursorMove.EndKey[J] THEN BEGIN
IF LENGTH(tLine) - Place+1 <> 0 THEN sCursorRight(LENGTH(tLine)-Place+1);
Place := BYTE(tLine[0])+1;
Temp := '';
END ELSE IF Temp = CursorMove.Left[J] THEN BEGIN
IF Place <> 1 THEN BEGIN
DEC(Place);
sCursorLeft(1);
END;
Temp := '';
END ELSE IF Temp = CursorMove.Right[J] THEN BEGIN
IF Place < BYTE(tLine[0])+1 THEN BEGIN
INC(Place);
sCursorRight(1);
END;
Temp := '';
END ELSE IF Temp = CursorMove.Insert[J] THEN BEGIN
Insrt := NOT Insrt;
Temp := '';
END ELSE IF Temp = CursorMove.Delete[J] THEN BEGIN
Temp := '';
IF Place < BYTE(tLine[0])+1 THEN BEGIN
DELETE(tLine,Place,1);
IF ShowIt THEN sWrite(COPY(tLine,Place,255)+BackSpaceChar)
ELSE sWrite(#25'■'+CHAR(BYTE(tLine[0]) - Place+1)+BackSpaceChar);
sCursorLeft(BYTE(tLine[0]) - Place+1+1);
END;
END;
INC(J);
UNTIL (J = Avatar) OR (Temp = '');
END;
#8 : IF Place <> 1 THEN BEGIN
IF Place = BYTE(tLine[0])+1 THEN BEGIN
DEC(tLine[0]);
sWrite(#8+BackSpaceChar{+#22#5}); {#22#5 is for Avatar}
DEC(Place);
sCursorLeft(1);
END ELSE BEGIN
DEC(Place);
DELETE(tLine,Place,1);
sCursorLeft(1);
IF ShowIt THEN sWrite(COPY(tLine,Place,255)+BackSpaceChar)
ELSE sWrite(#25'■'+CHAR(LENGTH(COPY(tLine,Place,255)))+BackSpaceChar);
sCursorLeft(LENGTH(COPY(tLine,Place,255)+BackSpaceChar));
END;
END;
#25: IF tLine[0] <> #0 THEN BEGIN
sCursorLeft(Place-1);
sWrite(#25+BackSpaceChar+CHAR(BYTE(tLine[0])));
sCursorLeft(BYTE(tLine[0]));
tLine := '';
Place := 1;
END;
#1..#31 : ;
ELSE BEGIN
IF (LENGTH(tLine) <> Len) OR ((NOT Insrt) AND (Place-1 <> Len)) THEN BEGIN
IF Place = LENGTH(tLine)+1 THEN BEGIN
IF ShowIt THEN sWrite(Ch) ELSE sWrite('■');
tLine := tLine + Ch;
INC(Place);
END ELSE BEGIN
IF NOT Insrt THEN BEGIN
IF ShowIt THEN sWrite(Ch) ELSE sWrite('■');
tLine[Place] := Ch;
INC(Place);
END ELSE BEGIN
INSERT(Ch,tLine,Place);
IF ShowIt THEN sWrite(COPY(tLine,Place,255))
ELSE sWrite(#25'■'+CHAR(LENGTH(COPY(tLine,Place,255))));
sCursorLeft(LENGTH(COPY(tLine,Place,255))-1);
INC(Place);
END;
END;
END ELSE BEGIN
IF NOT WrapInput THEN sWrite(#7)
ELSE BEGIN
Temp[0] := #0;
RTemp[0] := #0;
Loop := BYTE(tLine[0]);
IF POS(#32,tLine) <> 0 THEN BEGIN
WHILE (tLine[loop] <> #32) DO BEGIN
sWrite(#8+BackSpaceChar{+#22#5}); {#22#5 is for Avatar}
Temp := Temp + tLine[Loop];
DEC(Loop);
DEC(tLine[0]);
END;
IF Temp[0] <> #0 THEN FOR Loop := BYTE(Temp[0]) DOWNTO 1 DO RTemp := RTemp + Temp[Loop];
END;
Ch := #13;
END;
END;
END;
END;
UNTIL Ch = #13;
InputDriver := tLine;
sWriteln('');
END;
{ ────────────────────────────────────────────────────────────────────────── }
FUNCTION SecretInput(Len : BYTE; Default : STRING) : STRING;
BEGIN
SecretInput := InputDriver(Len,FALSE,FALSE,FALSE,FALSE,Default);
END;
{ ────────────────────────────────────────────────────────────────────────── }
FUNCTION NameInput(Len : BYTE; Default : STRING) : STRING;
BEGIN
NameInput := InputDriver(Len,TRUE,TRUE,FALSE,FALSE,Default);
END;
{ ────────────────────────────────────────────────────────────────────────── }
FUNCTION NormalInput(Len : BYTE; Default : STRING) : STRING;
BEGIN
NormalInput := InputDriver(Len,FALSE,TRUE,FALSE,FALSE,Default);
END;
{ ────────────────────────────────────────────────────────────────────────── }
FUNCTION CapsInput(Len : BYTE; Default : STRING) : STRING;
BEGIN
CapsInput := InputDriver(Len,FALSE,TRUE,TRUE,FALSE,Default);
END;
{ ────────────────────────────────────────────────────────────────────────── }
FUNCTION NumberInput(Len : BYTE; Default : STRING) : STRING;
BEGIN
NumberInput := InputDriver(Len,FALSE,TRUE,FALSE,TRUE,Default);
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION NamePrompt(StrLength : BYTE ; InStr : STRING) : STRING;
VAR
X,Y,Loop : BYTE;
BEGIN
X := WhereX + 1;
Y := WhereY;
BackSpaceChar := '_';
Set_Color(CS.Bfg,CS.Wbg);
sWriteC('[');
Set_Color(CS.Ffg,CS.Fbg);
sWrite(InStr);
FOR Loop := LENGTH(InStr) TO (StrLength - 1) DO sWriteC('_');
Set_Color(CS.Bfg,CS.Wbg);
sWriteC(']');
IF InStr = '' THEN sGotoXY(X,Y) ELSE sGotoXY(X+LENGTH(InStr),Y);
Set_Color(CS.Ffg,CS.Fbg);
NamePrompt := NameInput(StrLength,InStr);
Set_Color(7,0); {sClrEol};
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION NormalPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
VAR
X,Y,Loop : BYTE;
BEGIN
X := WhereX + 1;
Y := WhereY;
BackSpaceChar := '_';
Set_Color(CS.Bfg,CS.Wbg);
sWriteC('[');
Set_Color(CS.Ffg,CS.Fbg);
sWrite(InStr);
FOR Loop := LENGTH(InStr) TO (StrLength - 1) DO sWriteC('_');
Set_Color(CS.Bfg,CS.Wbg);
sWriteC(']');
IF InStr = '' THEN sGotoXY(X,Y) ELSE sGotoXY(X+LENGTH(InStr),Y);
Set_Color(CS.Ffg,CS.Fbg);
NormalPrompt := NormalInput(StrLength,InStr);
Set_Color(7,0); {sClrEol};
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION NumberPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
VAR
X,Y,Loop : BYTE;
BEGIN
X := WhereX + 1;
Y := WhereY;
BackSpaceChar := '_';
Set_Color(CS.Bfg,CS.Wbg);
sWriteC('[');
Set_Color(CS.Ffg,CS.Fbg);
sWrite(InStr);
FOR Loop := LENGTH(InStr) TO (StrLength - 1) DO sWriteC('_');
Set_Color(CS.Bfg,CS.Wbg);
sWriteC(']');
IF InStr = '' THEN sGotoXY(X,Y) ELSE sGotoXY(X+LENGTH(InStr),Y);
Set_Color(CS.Ffg,CS.Fbg);
NumberPrompt := NumberInput(StrLength,InStr);
Set_Color(7,0); {sClrEol};
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION SecretPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
VAR
X,Y,Loop : BYTE;
BEGIN
X := WhereX + 1;
Y := WhereY;
BackSpaceChar := '_';
Set_Color(CS.Bfg,CS.Wbg);
sWriteC('[');
Set_Color(CS.Ffg,CS.Fbg);
FOR Loop := 1 TO StrLength DO sWriteC('_');
Set_Color(CS.Bfg,CS.Wbg);
sWriteC(']');
IF InStr = '' THEN sGotoXY(X,Y) ELSE sGotoXY(X+LENGTH(InStr),Y);
Set_Color(CS.Ffg,CS.Fbg);
SecretPrompt := SecretInput(StrLength,InStr);
Set_Color(7,0); {sClrEol};
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION CapsPrompt(StrLength : BYTE ; InStr : STRING) : STRING;
VAR
X,Y,Loop : BYTE;
BEGIN
X := WhereX + 1;
Y := WhereY;
BackSpaceChar := '_';
OutTxt(CS.Bfg,CS.Wbg,'[');
Set_Color(CS.Ffg,CS.Fbg);
InStr := AllCaps(InStr); sWrite(InStr);
FOR Loop := LENGTH(InStr) TO (StrLength - 1) DO sWriteC('_');
OutTxt(CS.Bfg,CS.Wbg,']');
IF InStr = '' THEN sGotoXY(X,Y) ELSE sGotoXY(X+LENGTH(InStr),Y);
Set_Color(CS.Ffg,CS.Fbg);
CapsPrompt := CapsInput(StrLength,InStr);
Set_Color(7,0); {sClrEol};
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION SysField(X,Y,Style,StrLength : BYTE ; InStr : STRING) : STRING;
VAR {^ 0-Normal 1-Number 2-Name 3-Secret 4-Caps}
OldFg,
OldBg,
OldBr,
Loop : BYTE;
BEGIN
sGotoXY(X,Y);
OldFg := CS.Ffg;
OldBg := CS.Fbg;
OldBr := CS.Bfg;
CS.Ffg := 15;
CS.Fbg := 0;
CS.Bfg := 14;
CASE Style OF
0 : InStr := NormalPrompt(StrLength,InStr);
1 : InStr := NumberPrompt(StrLength,InStr);
2 : InStr := NamePrompt(StrLength,InStr);
3 : InStr := SecretPrompt(StrLength,InStr);
4 : InStr := CapsPrompt(StrLength,InStr);
END;
CS.Ffg := OldFg;
CS.Fbg := OldBg;
CS.Bfg := OldBr;
IF Style <> 3 THEN DummyField(X,Y,StrLength,InStr) ELSE DummyField(X,Y,StrLength,'');
SysField := InStr;
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DummyField(X,Y,StrLength : BYTE ; InStr : STRING);
VAR
Loop : BYTE;
BEGIN
OutTxtXY(X,Y,CS.Wh,CS.Wbg,' ');
OutTxtXY(X+1,Y,7,0,InStr);
FOR Loop := LENGTH(InStr) TO (StrLength-1) DO sWriteC('_');
OutTxt(CS.Wh,CS.Wbg,' ');
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DrawWin(X1,Y1,X2,Y2 : BYTE ; Title : STRING);
CONST
Vs : CHAR = '█';
Hs : CHAR = '▀';
Tl : CHAR = '┌';
Tr : CHAR = '┐';
Bl : CHAR = '└';
Br : CHAR = '┘';
H : CHAR = '─';
V : CHAR = '│';
VAR
L1,L2 : BYTE;
BEGIN
sGotoXY(X1,Y1);
OutTxt(CS.Hfg,CS.Hbg,' ' + Title);
FOR L1 := WHEREX TO X2 DO OutTxt(CS.Hfg,CS.Hbg,' ');
OutTxtXY(X1,Y1 + 1,CS.Wh,CS.Wbg,Tl);
FOR L1 := (X1 + 1) TO (X2 - 1) DO OutTxt(CS.Wh,CS.Wbg,H);
OutTxtXY(X2,Y1 + 1,CS.Wl,CS.Wbg,Tr); OutTxt(CS.Sfg,CS.Sbg,Vs);
FOR L1 := (Y1 + 2) TO (Y2 - 1) DO BEGIN
OutTxtXY(X1,L1,CS.Wh,CS.Wbg,V);
FOR L2 := (X1 + 1) TO (X2 - 1) DO OutTxt(CS.Wh,CS.Wbg,' ');
OutTxt(CS.Wl,CS.Wbg,V); OutTxt(CS.Sfg,CS.Sbg,Vs);
END;
OutTxtXY(X1,Y2,CS.Wh,CS.Wbg,Bl);
FOR L1 := (X1 + 1) TO (X2 - 1) DO OutTxt(CS.Wl,CS.Wbg,H);
OutTxtXY(X2,Y2,CS.Wl,CS.Wbg,Br); OutTxt(CS.Sfg,CS.Sbg,Vs);
sGotoXY(X1 + 2,Y2 + 1);
FOR L1 := (X1 + 2) TO (X2 + 1) DO OutTxt(CS.Sfg,CS.Sbg,Hs);
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ClearWin(X1,Y1,X2,Y2 : BYTE);
VAR
L1,L2 : BYTE;
BEGIN
FOR L1 := Y1 TO Y2 DO BEGIN
sGotoXY(X1,L1);
FOR L2 := X1 TO X2 DO OutTxt(CS.Wh,CS.Wbg,' ');
END;
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DrawButton(HotKey : CHAR ; Txt : STRING ; HighLight : BOOLEAN);
VAR
BL,BR : CHAR;
FG : BYTE;
BEGIN
BR := '▌'; BL := '▐';
OutTxt(8,0,BL);
IF HighLight THEN FG := 1 ELSE FG := 8;
IF HighLight THEN OutTxt(4,7,' ' + HotKey);
IF NOT HighLight THEN OutTxt(8,7,' ' + HotKey);
OutTxt(FG,7,Txt + ' ');
OutTxt(8,0,BR);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE SysButton(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
VAR
L1,Sfg,Sbg : BYTE;
Vs,Hs : CHAR;
BEGIN
Vs := '▄';
Hs := '▀';
OutTxtXY(X,Y,4,7,' ' + HotKey);
OutTxt(0,7,Txt + ' ');
OutTxt(0,CS.Wbg,Vs);
sGotoXY(X + 1,Y + 1);
FOR L1 := 1 TO (LENGTH(Txt) + 3) DO OutTxt(0,CS.Wbg,Hs);
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DrawMenu(X1,Y1,X2,Y2 : BYTE);
CONST
Vs : CHAR = '█';
Hs : CHAR = '▀';
Tl : CHAR = '┌';
Tr : CHAR = '┐';
Bl : CHAR = '└';
Br : CHAR = '┘';
H : CHAR = '─';
V : CHAR = '│';
VAR
L1,L2 : BYTE;
BEGIN
sGotoXY(X1,Y1);
OutTxtXY(X1,Y1,0,7,Tl);
FOR L1 := (X1 + 1) TO (X2 - 1) DO OutTxt(0,7,H);
OutTxtXY(X2,Y1,0,7,Tr);
FOR L1 := (Y1 + 1) TO (Y2 - 1) DO BEGIN
OutTxtXY(X1,L1,0,7,V);
FOR L2 := (X1 + 1) TO (X2 - 1) DO OutTxt(0,7,' ');
OutTxt(0,7,V);
OutTxt(CS.Sfg,CS.Sbg,Vs);
END;
OutTxtXY(X1,Y2,0,7,Bl);
FOR L1 := (X1 + 1) TO (X2 - 1) DO OutTxt(0,7,H);
OutTxtXY(X2,Y2,0,7,Br); OutTxt(CS.Sfg,CS.Sbg,Vs);
Set_Color(CS.Sfg,CS.Sbg);
sGotoXY(X1+2,Y2+1);
FOR L1 := (X1 + 2) TO (X2 + 1) DO sWriteC(Hs);
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE MenuItem(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
BEGIN
OutTxtXY(X,Y,1,7,HotKey);
OutTxt(0,7,Txt);
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE MenuLine(X,Y,L : BYTE);
VAR
Loop : BYTE;
BEGIN
OutTxtXY(X,Y,0,7,'├');
FOR Loop := 1 TO (L - 2) DO OutTxt(0,7,'─');
OutTxt(0,7,'┤');
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE MenuBarItem(X,Y : BYTE ; HotKey : CHAR ; Txt : STRING);
BEGIN
OutTxtXY(X,Y,4,7,HotKey);
OutTxt(0,7,Txt);
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE InfoBox(Width : BYTE ; Height : BYTE);
CONST
LTC : CHAR = '╔';
RTC : CHAR = '╗';
LBC : CHAR = '╚';
RBC : CHAR = '╝';
HBAR : CHAR = '═';
VBAR : CHAR = '║';
VAR
Row,Loop : BYTE;
BEGIN
Row := WhereY;
Set_Color(9,0);
sGotoXY(1,Row); sWriteC(LTC);
FOR Loop := 2 TO (Width-1) DO sWriteC(HBAR);
Set_Color(1,0); sWritelnC(RTC);
Row := WhereY;
FOR Loop := 1 TO Height DO BEGIN
Set_Color(9,0);
sGotoXY(1,Row); sWriteC(VBAR);
Set_Color(1,0);
sGotoXY(Width,Row); sWritelnC(VBAR);
Row := WhereY;
END;
Set_Color(9,0);
sWriteC(LBC);
Set_Color(1,0);
FOR Loop := 2 TO (Width-1) DO sWriteC(HBAR);
sGotoXY(Width,Row); sWritelnC(RBC);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE InfoText(Txt : STRING);
VAR
LB,RB : STRING[4];
BEGIN
LB := '░▒▓█';
RB := '█▓▒░';
Set_Color(1,0); sWrite(LB);
Set_Color(15,1); sWrite(Txt);
Set_Color(1,0); sWrite(RB);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE LineBar(FG,BG,L : BYTE);
VAR
Loop : BYTE;
BEGIN
Set_Color(FG,BG);
FOR Loop := 1 TO L DO sWriteC('─');
sWriteln('');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE RunEntryForm(ScriptFile : STRING);
TYPE EntryFields = ARRAY[1..50] OF STRING;
VAR
Go1,
Go2,Go3,
GotText : BOOLEAN;
OldGfx,
Loop,FC : BYTE;
Scrn,
InFile,
OutFile : Text;
Cmd,
V1,V2,
ScrLine : STRING;
_Field : ^EntryFields;
BEGIN
IF NOT FExist(ScriptFile) THEN EXIT;
NEW(_Field);
sClrScr;
GotText := FALSE; FC := 0;
ASSIGN(InFile,ScriptFile);
RESET(InFile);
WHILE NOT EOF(InFile) DO BEGIN
Go1 := TRUE; Go2 := FALSE; Go3 := FALSE;
Cmd := ''; V1 := ''; V2 := '';
READLN(InFile,ScrLine);
ScrLine := CvtVars(ScrLine);
FOR Loop := 1 TO LENGTH(ScrLine) DO BEGIN
IF (Go2) AND (ScrLine[Loop] = '@') THEN BEGIN
Go1 := FALSE;
Go2 := FALSE;
Go3 := TRUE;
END;
IF Go1 THEN Cmd := Cmd + ScrLine[Loop];
IF Go2 THEN V1 := V1 + ScrLine[Loop];
IF (Go3) AND (ScrLine[Loop] <> '@') THEN V2 := V2 + ScrLine[Loop];
IF (Go1) AND (ScrLine[Loop] = '@') THEN BEGIN
Go1 := FALSE;
Go2 := TRUE;
Go3 := FALSE;
END;
END;
Cmd := AllCaps(Cmd);
IF Cmd = 'SCREENFILE@' THEN BEGIN
V1 := AllCaps(V1);
OldGfx := Graphics;
CASE Graphics OF
RIP : IF FExist(V1 + '.RIP') THEN ShowScreen(V1 + '.RIP')
ELSE BEGIN
RipToText;
Graphics := ANSI;
END;
ANSI : IF FExist(V1 + '.ANS') THEN ShowScreen(V1 + '.ANS')
ELSE Graphics := TTY;
TTY : ShowScreen(V1 + '.ASC');
END;
sWriteln('');
Graphics := OldGfx;
END;
IF (Cmd = 'TEXTFILE@') AND (NOT GotText) THEN BEGIN
GotText := TRUE;
V1 := AllCaps(V1);
ASSIGN(OutFile,V1);
IF NOT FExist(V1) THEN REWRITE(OutFile) ELSE APPEND(OutFile);
END;
IF Cmd = 'PROMPTTEXT@' THEN BEGIN
Set_Color(CS.CPTfg,CS.CPTbg);
CvtColors(V1,FALSE);
END;
IF Cmd = 'LINEFEED@' THEN sWriteln('');
IF Cmd = 'ANYKEY@' THEN AnyKey;
IF Cmd = 'PROPERPROMPT@' THEN BEGIN
INC(FC); sWriteC(' ');
IF Graphics = TTY THEN _Field^[FC] := NameInput(StrToInt(V1),V2)
ELSE _Field^[FC] := NamePrompt(StrToInt(V1),V2);
END;
IF Cmd = 'NORMALPROMPT@' THEN BEGIN
INC(FC); sWriteC(' ');
IF Graphics = TTY THEN _Field^[FC] := NormalInput(StrToInt(V1),V2)
ELSE _Field^[FC] := NormalPrompt(StrToInt(V1),V2);
END;
IF Cmd = 'NUMBERPROMPT@' THEN BEGIN
INC(FC); sWriteC(' ');
IF Graphics = TTY THEN _Field^[FC] := NumberInput(StrToInt(V1),V2)
ELSE _Field^[FC] := NumberPrompt(StrToInt(V1),V2);
END;
IF Cmd = 'CAPITALPROMPT@' THEN BEGIN
INC(FC); sWriteC(' ');
IF Graphics = TTY THEN _Field^[FC] := CapsInput(StrToInt(V1),V2)
ELSE _Field^[FC] := CapsPrompt(StrToInt(V1),V2);
END;
IF Cmd = 'HIDDENPROMPT@' THEN BEGIN
INC(FC); sWriteC(' ');
IF Graphics = TTY THEN _Field^[FC] := SecretInput(StrToInt(V1),V2)
ELSE _Field^[FC] := SecretPrompt(StrToInt(V1),V2);
END;
IF Cmd = 'OUTTEXT@' THEN BEGIN
IF V2 <> '' THEN WRITE(OutFile,V1)
ELSE WRITELN(OutFile,V1);
IF (V2 <> '') AND (StrToInt(V2) <= FC) THEN WRITELN(OutFile,_Field^[StrToInt(V2)]);
END;
IF Cmd = 'RUNBATCHFILE@' THEN RunBatFile(V1);
IF Cmd = 'SHOWTEXTFILE@' THEN ShowTextFile(V1);
IF Cmd = 'CLS@' THEN sClrScr;
END;
DISPOSE(_Field);
IF GotText THEN CLOSE(OutFile);
CLOSE(InFile);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE Log(LogLine : STRING);
VAR
TheLog : Text;
BEGIN
IF (NOT UseLog) Or (LogFile = '') THEN EXIT;
ASSIGN(TheLog,LogPath+LogFile);
IF NOT FExist(LogPath+LogFile) THEN BEGIN
REWRITE(TheLog);
CLOSE(TheLog);
END;
APPEND(TheLog);
IF (LogLine = 'BEGIN') AND (NOT Shotgun) THEN BEGIN
WRITELN(TheLog,'───────────────────────────────────────────────────────────────────────────────');
WRITELN(TheLog,' Activity Log Created By: '+ProgramName);
WRITELN(TheLog,'──────────┬────────────────────────────────────────────────────────────────────');
END;
IF (LogLine <> 'BEGIN') AND (LogLine <> 'END') THEN WRITELN(TheLog,' '+TimeVariable+' │ '+LogLine);
IF (LogLine = 'END') AND (NOT Shotgun) THEN
WRITELN(TheLog,'──────────┴────────────────────────────────────────────────────────────────────');
CLOSE(TheLog);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE Terminate(S : STRING);
BEGIN
TextAttr := 7;
CLRSCR;
TextAttr := 12;
WRITELN(S);
AlertTones;
TextAttr := 7;
DELAY(1000);
HALT(ErrLevel);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ErrorLog(LogLine : STRING ; ELevel : BYTE ; BailOut : BOOLEAN);
VAR
LogFile : Text;
BEGIN
ASSIGN(LogFile,LogPath+'ERROR.LOG');
IF NOT FExist(LogPath+'ERROR.LOG') THEN BEGIN
REWRITE(LogFile);
WRITELN(LogFile,' Error Log Created By: '+ProgramName);
WRITELN(LogFile,'──────────┬────────────────────────────────────────────────────────────────────');
CLOSE(LogFile);
END;
APPEND(LogFile);
WRITELN(LogFile,' '+TimeVariable+' │ '+LogLine);
IF BailOut THEN WRITELN(LogFile,' '+TimeVariable+' │ Exiting At ErrorLevel '+IntToStr(ELevel));
CLOSE(LogFile);
ErrLevel := ELevel;
IF BailOut THEN Terminate(LogLine);
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION GoodColor(TempStr : STRING) : BOOLEAN;
VAR
FG : BYTE;
BEGIN
FG := 50;
IF TempStr = '{0}' THEN FG := 0;
IF TempStr = '{1}' THEN FG := 1;
IF TempStr = '{2}' THEN FG := 2;
IF TempStr = '{3}' THEN FG := 3;
IF TempStr = '{4}' THEN FG := 4;
IF TempStr = '{5}' THEN FG := 5;
IF TempStr = '{6}' THEN FG := 6;
IF TempStr = '{7}' THEN FG := 7;
IF TempStr = '{8}' THEN FG := 8;
IF TempStr = '{9}' THEN FG := 9;
IF TempStr = '{10}' THEN FG := 10;
IF TempStr = '{11}' THEN FG := 11;
IF TempStr = '{12}' THEN FG := 12;
IF TempStr = '{13}' THEN FG := 13;
IF TempStr = '{14}' THEN FG := 14;
IF TempStr = '{15}' THEN FG := 15;
IF TempStr = '{16}' THEN FG := 16;
IF TempStr = '{17}' THEN FG := 17;
IF TempStr = '{18}' THEN FG := 18;
IF TempStr = '{19}' THEN FG := 19;
IF TempStr = '{20}' THEN FG := 20;
IF TempStr = '{21}' THEN FG := 21;
IF TempStr = '{22}' THEN FG := 22;
IF TempStr = '{23}' THEN FG := 23;
IF TempStr = '{24}' THEN FG := 24;
IF TempStr = '{25}' THEN FG := 25;
IF TempStr = '{26}' THEN FG := 26;
IF TempStr = '{27}' THEN FG := 27;
IF TempStr = '{28}' THEN FG := 28;
IF TempStr = '{29}' THEN FG := 29;
IF TempStr = '{30}' THEN FG := 30;
IF TempStr = '{31}' THEN FG := 31;
IF FG <> 50 THEN BEGIN
SetFore(FG);
GoodColor := TRUE;
END ELSE GoodColor := FALSE;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE CvtColors(InStr : STRING ; LF : BOOLEAN);
VAR
Loop : BYTE;
Cvt : BOOLEAN;
Temp : STRING;
BEGIN
Cvt := FALSE;
Temp := '';
FOR Loop := 1 TO LENGTH(InStr) DO BEGIN
IF InStr[Loop] = '{' THEN Cvt := TRUE;
IF NOT Cvt THEN sWriteC(InStr[Loop]);
IF Cvt THEN Temp := Temp + InStr[Loop];
IF (Cvt) AND (InStr[Loop] = '}') THEN BEGIN
IF NOT GoodColor(Temp) THEN sWrite(Temp);
Cvt := FALSE;
Temp := '';
END;
END;
IF LF THEN sWriteln('');
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION CvtVars(Txt : STRING) : STRING;
VAR
Cvt : BOOLEAN;
Loop : BYTE;
Parm,
Temp : STRING;
BEGIN
Cvt := FALSE; Parm := ''; Temp := '';
FOR Loop := 1 TO LENGTH(Txt) DO BEGIN
IF Txt[Loop] = '{' THEN Cvt := TRUE;
IF NOT Cvt THEN Parm := Parm + Txt[Loop];
IF Cvt THEN Temp := Temp + Txt[Loop];
IF Txt[Loop] = '}' THEN BEGIN
IF Temp = '{TIME}' THEN Temp := TimeVariable;
IF Temp = '{DATE}' THEN Temp := DateVariable;
IF Temp = '{NODE}' THEN Temp := IntToStr(DoorSys.Node);
IF Temp = '{BAUD}' THEN Temp := IntToStr(DoorSys.BaudRate);
IF Temp = '{MINS}' THEN Temp := IntToStr(DoorSys.SecondsLeft DIV 60);
IF Temp = '{EVENT}' THEN Temp := IntToStr(DoorSys.Event);
IF Temp = '{PORT}' THEN Temp := IntToStr(DoorSys.Comport);
IF Temp = '{SEC}' THEN Temp := IntToStr(DoorSys.Access);
IF Temp = '{BBS}' THEN Temp := Ctl.BBSname;
IF Temp = '{USER}' THEN Temp := DoorSys.UserName;
IF Temp = '{USER#}' THEN Temp := IntToStr(DoorSys.UserNumber);
IF Temp = '{SYSOP}' THEN Temp := Ctl.SFirst+' '+Ctl.SLast;
IF Temp = '{UFIRST}' THEN Temp := UFirst;
IF Temp = '{ULAST}' THEN Temp := ULast;
IF Temp = '{SFIRST}' THEN Temp := Ctl.SFirst;
IF Temp = '{SLAST}' THEN Temp := Ctl.SLast;
IF Temp = '{PROG}' THEN Temp := ProgramName;
IF Temp = '{ADDR}' THEN Temp := Ctl.HexAddr;
IF Temp = '{IRQ}' THEN Temp := IntToStr(Ctl.IRQ);
IF Temp = '{SYSSEC}' THEN Temp := IntToStr(Ctl.SysSec);
IF Temp = '{SERIAL}' THEN Temp := Ctl.SerialNumber;
IF Temp = '{INSERT1}' THEN Temp := Insert1;
IF Temp = '{INSERT2}' THEN Temp := Insert2;
IF Temp = '{INSERT3}' THEN Temp := Insert3;
IF Temp = '{INSERT4}' THEN Temp := Insert4;
IF Temp = '{INSERT5}' THEN Temp := Insert5;
Parm := Parm + Temp;
Temp := '';
Cvt := FALSE;
END;
END;
IF (Cvt) AND (Loop = LENGTH(Txt)) THEN Parm := Parm + Temp;
CvtVars := Parm;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION DateVariable : STRING;
VAR
Mo,
Da,Yr : STRING[4];
Year,Month,
Day,Dow : WORD;
BEGIN
GETDATE(Year,Month,Day,Dow);
STR(Year,Yr); DELETE(Yr,1,2);
STR(Month,Mo);
IF Month < 10 THEN Mo := '0' + Mo;
STR(Day,Da);
IF Day < 10 THEN Da := '0' + Da;
DateVariable := Mo + '/' + Da + '/' + Yr;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION TimeVariable : STRING;
VAR
TStr,
Hr,Mn : STRING[2];
Hour,Min,
Sec,Sec100 : WORD;
BEGIN
GETTIME(Hour,Min,Sec,Sec100);
IF Hour < 12 THEN TStr := 'am' ELSE TStr := 'pm';
IF Hour = 0 THEN Hour := 12;
IF Hour > 12 THEN Hour := Hour - 12;
STR(Hour,Hr);
STR(Min,Mn);
IF Min < 10 THEN Mn := '0' + Mn;
IF Min = 0 THEN Mn := '00';
IF Hour < 10 THEN Hr := ' ' + Hr;
TimeVariable := Hr + ':' + Mn + TStr;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE RipToText;
BEGIN
Set_Color(0,0);
sClrScr;
sWriteln(#13#10);
sWriteln('!|1K|*|#|#|#'+#13);
Set_Color(7,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ShowTextFile(TextFile : STRING);
TYPE TextData = RECORD
TLine : STRING[128];
END;
VAR
T : TextData;
TDat : FILE OF TextData;
Ch : CHAR;
Count : BYTE;
Loop,Cnt : INTEGER;
File_Name : Text;
BEGIN;
IF Graphics = RIP THEN RipToText;
sClrScr;
ASSIGN(File_Name,TextFile);
ASSIGN(TDat,GetFilePath(TextFile)+'TEXT'+IntToStr(DoorSys.Node)+'.DAT');
IF NOT FExist(TextFile) THEN EXIT;
RESET(File_Name);
REWRITE(TDat);
Cnt := 0;
WHILE NOT EOF (File_Name) DO BEGIN
READLN(File_Name,T.TLine);
FOR Count := 1 TO LENGTH(T.TLine) DO IF T.TLine[Count] = '' THEN T.TLine[Count] := ' ';
T.TLine := CvtVars(T.TLine);
SEEK(TDat,Cnt);
WRITE(TDat,T);
INC(Cnt);
END;
DEC(Cnt);
CLOSE(File_Name);
RESET(TDat);
Count := 1;
FOR Loop := 0 TO Cnt DO BEGIN
SEEK(TDat,Loop);
READ(TDat,T);
Set_Color(CS.TxFG,CS.TxBG);
CvtColors(T.TLine,TRUE);
INC(Count);
IF (Count = 22) OR (Loop = Cnt) THEN BEGIN
LineBar(1,0,79);
CPrompt('Q','uit'); CPrompt('T','op'); CPrompt('B','ottom'); CPrompt('P','revious'); CPrompt('N','ext');
Ch := UPCASE(sReadKey);
CASE Ch OF
'Q' : BEGIN
CLOSE(TDat);
ERASE(TDat);
EXIT;
END;
'T' : Loop := 0 - 1;
'B' : Loop := Cnt - 21;
'P' : BEGIN
DEC(Loop,45);
IF Loop < 0 THEN Loop := 0 - 1;
END;
END;
Count := 1;
IF Loop <> Cnt THEN sClrScr;
END;
END;
CLOSE(TDat);
ERASE(TDat);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ShowScreen(Scr : STRING);
VAR
LN : STRING;
File_Name : Text;
BEGIN;
IF NOT FExist(Scr) THEN EXIT;
IF Graphics = RIP THEN BEGIN
Set_Color(0,0);
sWriteln(#13#10);
sWriteln(#12#13);
END;
ASSIGN(File_Name,Scr);
RESET(File_Name);
HideCursor;
WHILE NOT EOF(File_Name) DO BEGIN
READLN(File_Name,LN);
LN := CvtVars(LN);
CASE Graphics OF
MAX : SendStr(LN);
RIP : SendStr(LN);
ANSI : BEGIN
SendStr(LN);
AnsiWriteln(LN);
END;
TTY : sWriteln(LN);
END;
END;
ShowCursor;
CLOSE(File_Name);
CASE Graphics OF
RIP : DVWrite(1,2,15,'Displaying RIP File: '+PadRight(Scr,' ',12));
MAX : DVWrite(1,2,15,'Displaying MAX File: '+PadRight(Scr,' ',12));
END;
IF Graphics <> TTY THEN sGotoXY(VirtX,VirtY);
Set_Color(7,0); sClrEol;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE FullScreenChat;
VAR
FG,
Loop,
UserX,
UserY,
SysopX,
SysopY : BYTE;
Quit : BOOLEAN;
Ch : CHAR;
Temp : STRING;
BEGIN
DoorSys.UpdateSecs := FALSE;
DoorSys.UpdateIdle := FALSE;
sClrScr;
InfoText(Center(ProgramName,71));
sGotoXY(1,2); InfoBox(79,8);
InfoText(Center(ProgramDesc,71));
sGotoXY(1,13); InfoBox(79,8);
InfoText('CTRL-W (Clear Window) CTRL-Y (Clear Line)');
DVWrite(1,24,8,Center('Press The ESCape Key To Terminate Chat Mode!',79));
OutTxtXY(3,2,10,0,' ' + #31 + ' ' + Ctl.SFirst + ' ' + Ctl.SLast + ' ' + #31 + ' ');
OutTxtXY(3,13,14,0,' ' + #31 + ' ' + DoorSys.UserName + ' ' + #31 + ' ');
SysopX := 2;
SysopY := 3;
UserX := 2;
UserY := 14;
Quit := FALSE;
sGotoXY(2,3);
IF Local THEN DoorSys.LocalKey := TRUE;
REPEAT
REPEAT
Ch := sReadKey;
UNTIL Ch IN [#0,#8,#13,#23,#25,#27,' '..#255];
CASE Ch OF
'A'..'Z' : FG := 15;
'a'..'z' : FG := 11;
#0 : BEGIN
sReadKey;
Ch := #0;
END;
#8 : IF DoorSys.LocalKey THEN BEGIN
DEC(SysopX);
IF SysopX < 2 THEN SysopX := 2;
Ch := #0;
OutTxtXY(SysopX,SysopY,10,0,' ');
sGotoXY(SysopX,SysopY);
END ELSE BEGIN
DEC(UserX);
IF UserX < 2 THEN UserX := 2;
Ch := #0;
OutTxtXY(UserX,UserY,14,0,' ');
sGotoXY(UserX,UserY);
END;
#13 : IF DoorSys.LocalKey THEN BEGIN
SysopX := 2;
INC(SysopY);
IF SysopY > 10 THEN SysopY := 3;
sGotoXY(SysopX,SysopY);
sWrite(PadRight(' ',' ',77));
IF SysopY < 10 THEN sGotoXY(SysopX,SysopY + 1) ELSE sGotoXY(SysopX,3);
sWrite(PadRight(' ',' ',77));
sGotoXY(SysopX,SysopY);
Ch := #0;
END ELSE BEGIN
UserX := 2;
INC(UserY);
IF UserY > 21 THEN UserY := 14;
sGotoXY(UserX,UserY);
sWrite(PadRight(' ',' ',77));
IF UserY < 21 THEN sGotoXY(UserX,UserY + 1) ELSE sGotoXY(UserX,14);
sWrite(PadRight(' ',' ',77));
sGotoXY(UserX,UserY);
Ch := #0;
END;
#23 : IF DoorSys.LocalKey THEN BEGIN
FOR Loop := 3 TO 10 DO OutTxtXY(2,Loop,7,0,PadRight(' ',' ',77));
SysopX := 2;
SysopY := 3;
sGotoXY(SysopX,SysopY);
Ch := #0;
END ELSE BEGIN
FOR Loop := 14 TO 21 DO OutTxtXY(2,Loop,7,0,PadRight(' ',' ',77));
UserX := 2;
UserY := 14;
sGotoXY(UserX,UserY);
Ch := #0;
END;
#25 : IF DoorSys.LocalKey THEN BEGIN
SysopX := 2;
sGotoXY(SysopX,SysopY);
sWrite(PadRight(' ',' ',77));
sGotoXY(SysopX,SysopY);
Ch := #0;
END ELSE BEGIN
UserX := 2;
sGotoXY(UserX,UserY);
sWrite(PadRight(' ',' ',77));
sGotoXY(UserX,UserY);
Ch := #0;
END;
#27 : IF NOT DoorSys.LocalKey THEN BEGIN
DELAY(50);
WHILE sKeyPressed DO sReadKey;
Ch := #0;
END;
ELSE FG := 9;
END;
Quit := Ch = #27;
IF (NOT Quit) AND (Ch <> #0) AND (Ch <> #27) THEN BEGIN
IF DoorSys.LocalKey THEN BEGIN
OutTxtXY(SysopX,SysopY,FG,0,Ch);
INC(SysopX);
IF SysopX = 79 THEN BEGIN
SysopX := 2;
INC(SysopY);
IF SysopY > 10 THEN SysopY := 3;
sGotoXY(SysopX,SysopY);
sWrite(PadRight(' ',' ',77));
IF SysopY < 10 THEN sGotoXY(SysopX,SysopY + 1) ELSE sGotoXY(SysopX,3);
sWrite(PadRight(' ',' ',77));
END;
sGotoXY(SysopX,SysopY);
END ELSE BEGIN
OutTxtXY(UserX,UserY,FG,0,Ch);
INC(UserX);
IF UserX = 79 THEN BEGIN
UserX := 2;
INC(UserY);
IF UserY > 21 THEN UserY := 14;
sGotoXY(UserX,UserY);
sWrite(PadRight(' ',' ',77));
IF UserY < 21 THEN sGotoXY(UserX,UserY + 1) ELSE sGotoXY(UserX,14);
sWrite(PadRight(' ',' ',77));
END;
sGotoXY(UserX,UserY);
END;
END;
UNTIL Quit;
DoorSys.UpdateSecs := TRUE;
DoorSys.UpdateIdle := TRUE;
Set_Color(7,0);
sClrScr;
PurgeInput;
AnyKey;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE LineChat;
CONST
SysopText : BYTE = 11;
CallerText : BYTE = 3;
VAR
InputKey : CHAR;
Loop,I : BYTE;
CL,
Temp,
RTemp,
Movement : STRING;
OldLocalKey : BOOLEAN;
BEGIN
DoorSys.UpdateSecs := FALSE;
DoorSys.UpdateIdle := FALSE;
CL[0] := #0;
Movement[0] := #0;
OutTxtL(15,0,Ctl.SFirst+' '+Ctl.SLast+' Is Here At Your Services....');
TextAttr := SysopText;
OldLocalKey := TRUE;
REPEAT
InputKey := sReadkey;
IF DoorSys.LocalKey <> OldLocalKey THEN BEGIN
IF DoorSys.LocalKey THEN TextAttr := SysopText ELSE TextAttr := CallerText;
OldLocalKey := DoorSys.LocalKey;
END;
IF WrapLength <= BYTE(CL[0]) THEN BEGIN
Temp[0] := #0;
RTemp[0] := #0;
Loop := BYTE(CL[0]);
IF POS(#32,CL) <> 0 THEN WHILE (CL[loop] <> #32) DO BEGIN
sWrite(#8#32#8);
Temp := Temp + CL[Loop];
DEC(Loop);
END ELSE WHILE (Loop >= WrapLength) DO BEGIN
sWrite(#8#32#8);
Temp := Temp + CL[Loop];
DEC(Loop);
END;
IF Temp[0] <> #0 THEN FOR Loop := BYTE(Temp[0]) DOWNTO 1 DO RTemp := RTemp + Temp[Loop];
sWrite(#13+RTemp);
CL := RTemp;
END;
IF (NOT (Inputkey IN [#13,#27,#8,#27,#0])) THEN BEGIN
AnsiWrite(InputKey);
CL := CL + InputKey;
END ELSE
CASE InputKey OF
#0 : Movement := InputKey + sReadKey;
#8 : IF CL <> '' THEN BEGIN
sWrite(#8#32#8);
DEC(CL[0]);
END;
#13 : BEGIN
sWriteln('');
CL := '';
END;
#22 : BEGIN
sWaitInput(250);
Movement := InputKey;
IF sKeyPressed THEN Movement := Movement + sReadKey;
END;
#27 : IF NOT DoorSys.LocalKey THEN Movement := InputKey + sReadKey + sReadKey;
END;
IF Movement <> '' THEN BEGIN
FOR Loop := Tty TO Ansi DO BEGIN
IF Movement = CursorMove.Up[Loop] THEN BEGIN
sCursorUp(1);
Movement := '';
END ELSE IF Movement = CursorMove.Down[Loop] THEN BEGIN
sCursorDown(1);
Movement := '';
END ELSE IF Movement = CursorMove.Left[Loop] THEN BEGIN
sCursorLeft(1);
Movement := '';
END ELSE IF Movement = CursorMove.Right[Loop] THEN BEGIN
sCursorRight(1);
Movement := '';
END ELSE IF Movement = CursorMove.Home[Loop] THEN BEGIN
sCursorLeft(250);
Movement := '';
END ELSE IF Movement = CursorMove.EndKey[Loop] THEN BEGIN
sCursorRight(250);
Movement := '';
END;
END;
IF Movement <> '' THEN BEGIN
FOR I := 1 TO LENGTH(Movement) DO AnsiWrite(Movement[I]);
Movement := '';
END;
END;
UNTIL (DoorSys.LocalKey AND (InputKey = #27));
DoorSys.UpdateSecs := TRUE;
DoorSys.UpdateIdle := TRUE;
Set_Color(7,0);
sClrScr;
PurgeInput;
AnyKey;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ChatSelect;
BEGIN
IF Graphics = RIP THEN RipToText;
IF Graphics = TTY THEN LineChat ELSE FullScreenChat;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DVWrite(X,Y : WORD; Attr : BYTE; S : STRING); Assembler;
{X and Y are 1 based, not 0 zero based!}
Asm
push ds
mov bx,[y]
DEC bx
SHL bx,1
mov ax,bx
{$ifopt G+}
SHL bx,2
{$else}
SHL bx,1
SHL bx,1
{$endif}
add ax,bx
add ax,[DVseg]
mov es,ax
mov di,[x]
DEC di
SHL di,1
add di,[DVofs]
lds si,s
mov cl,BYTE PTR [si]
INC si
mov ah,attr
@1 :
mov al,BYTE PTR [si]
mov WORD PTR es : [di],ax
INC si
add di,2
DEC cl
jnz @1
pop ds
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE AlertTones;
VAR
Loop : BYTE;
BEGIN
FOR Loop := 1 TO 5 DO BEGIN
IF NOT Local THEN SendStr(^G) ELSE WRITE(^G);
DELAY(200);
END
END;
{ ────────────────────────────────────────────────────────────────────────── }
END.